package ControlLayer;

import ModelLayer.*;
import java.util.HashMap;
import java.util.ArrayList;
import java.lang.StringBuilder;
/**
 * This class is part of an address book system. It functions as a controller for the LoanCon class in
 * the ModelLayer. Any changes to LoanCon or Loan classes will go through this class.
 * This class is used through the system UI, more specifically LoanUI.
 *
 * @author Anders A.P., Anna K., Danny M.P., Jakob K., Mie P.  
 * @version 1.0
 */
public class LoanCtr
{
    private LoanCon loanCon;

    /**
     * Constructs an instance of class LoanCtr, taking no parameters. Takes an instance of the singleton class LoanCon.
     */
    public LoanCtr() 
    {
        loanCon = LoanCon.getInstance();
    }

    /**
     * Finds an object of class Person, taking the follow parameter:
     *
     * @param   id          Person objects ID, using this as a key in the HashMap addrCon.
     * @return  Person      Returns a Person object
     */
    public Person findLoaner(String id) 
    {
        AddressCtr addrCtr = new AddressCtr();
        return addrCtr.findLoaner(id);
    }

    /**
     * Finds an available copy which is currently not lend out, using title as parameter.
     *
     * @param   title   Title of the DVD the copy is an aggregation of.
     * @return  Copy    An object of class Copy that is an aggregation of class DVD.
     */
    public Copy findCopy(String title) 
    {
        DVDCtr dvdCtr = new DVDCtr();
        HashMap<Integer, Copy> copyMap = dvdCtr.findCopy(title);
        Copy availableCopy = null;
        boolean found = false;
        
        for(Copy copy : copyMap.values()) {
            for(Loan loan : loanCon.getMap().values()) {
                if(loan.getCopy().equals(copy) && loan.getState() == true) {
                    found = true;
                }
            }
            if (!found) {
                availableCopy = copy;
            }
            found = false;
        }
        return availableCopy; 
    }

    /**
     * Creates a Loan object and stores it in the container.
     * 
     * @param   id          Loan ID. 
     * @param   title       DVD title. 
     * @param   fromDate    The date the loan begins.
     * @param   toDate      The expected date the loan is returned. 
     */
    public void createLoan(String id, String title, String fromDate, String toDate) 
    {
        //DEMO exceptions added, prevent null in loaner and copy
        //loanCon.addLoan(new Loan(fromDate, toDate, this.findLoaner(id), this.findCopy(title)));
        Person loaner = this.findLoaner(id);
        if (loaner == null){
            throw new  IllegalArgumentException("Loaner " + id + " not found"); 
        }
        Copy copy = this.findCopy(title);
        if (copy == null){
            throw new IllegalArgumentException("Copy " + title + " not found");
        }
        loanCon.addLoan(new Loan(fromDate, toDate, loaner, copy));
    }

    /**
     * Returns a list of all Loan objects contained in the collection.
     *
     * @return  String  A list of all loans in the loanCon collection.
     */
    public String listAll() 
    {   
        StringBuilder stringBuilder = new StringBuilder();
        ArrayList<Loan> loanList = loanCon.listAll();          
        if(loanList.size() != 0) {    
            for(Loan l : loanList){
                stringBuilder.append("\n" + l.getPerson().getName() + "\n" + 
                                     l.getCopy().getSerialNr() + ":" + findDVDByCopy(l.getCopy()).getTitle() + "\n" + 
                                     l.getFromDate() + " - " +
                                     l.getToDate() + "\n" +
                                     //"lent out: " + l.getState() + "\n");
                                     (l.getState() ? "lent out" : "home") + "\n");
                                     
            }
            return stringBuilder.toString();
        }
        return null;
    } 

    /**
     * Finds all loans in the HashMap by person name.
     *
     * @param   name    The name used to find the Person object.
     * @return  String  Returns a String object containing Loan object's field values constructed 
     *                  using a StringBuilder object.
     */    
    public String findLoan(String name)
    {
        StringBuilder stringBuilder = new StringBuilder();
        ArrayList<Loan> loanList = loanCon.getLoanName(name);        
        if(loanList.size() != 0) {
            for(Loan l : loanList) {
                stringBuilder.append("\n" + l.getPerson().getName() + "\n" +
                                     l.getID() + ": " + findDVDByCopy(l.getCopy()).getTitle() + "\n" +
                                     l.getFromDate() + " - " +
                                     l.getToDate() + "\n");
            }
            return stringBuilder.toString();
        }
        return null;
    }
    
    //DEMO Method to find associated DVD to copy. Can be used fx to find title of the copy.
    public DVD findDVDByCopy(Copy c){
        for (DVD dvd : DVDCon.getInstance().listAll()){
             if (dvd.getCopies().values().contains(c)){
                return dvd;
             }
        }
        return null;
    }
    
    /**
     * Registers when a DVD is returned.
     *
     * @param   id          Loan ID
     * @param   isTooLate   Boolean value, stating wether the DVD is returned or not.
     *                      true: is not returned.
     *                      false: is returned.
     */
    public void returnDVD(int id, boolean isTooLate)
    {
        Loan l = loanCon.getLoan(id);
        if (!isTooLate) {
            l.setState(false);
        }
        l.setIsTooLate(true);
        l.setState(false);
    }
}

